package cn.iocoder.an.module.business.controller.admin.equipmentmanage;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.an.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.an.module.business.dal.dataobject.equipmentcheckplan.EquipmentCheckPlanDO;
import cn.iocoder.an.module.business.dal.dataobject.warningconfig.WarningConfigDO;
import cn.iocoder.an.module.business.dal.mysql.equipmentcheckplan.EquipmentCheckPlanMapper;
import cn.iocoder.an.module.business.dal.mysql.warningconfig.WarningConfigMapper;
import cn.iocoder.an.module.business.enums.EquipmentStatusEnum;
import cn.iocoder.an.module.business.enums.EquipmentTypeEnum;
import cn.iocoder.an.module.business.enums.EquipmentUsedEnum;
import cn.iocoder.an.module.business.service.equipmentkeepconfig.EquipmentKeepConfigService;
import cn.iocoder.an.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.an.module.system.service.user.AdminUserService;
import com.fhs.core.trans.anno.TransMethodResult;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import jakarta.validation.*;
import jakarta.servlet.http.*;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;

import cn.iocoder.an.framework.common.pojo.PageParam;
import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.pojo.CommonResult;
import cn.iocoder.an.framework.common.util.object.BeanUtils;

import static cn.iocoder.an.framework.common.pojo.CommonResult.success;

import cn.iocoder.an.framework.excel.core.util.ExcelUtils;

import cn.iocoder.an.framework.apilog.core.annotation.ApiAccessLog;

import static cn.iocoder.an.framework.apilog.core.enums.OperateTypeEnum.*;

import cn.iocoder.an.module.business.controller.admin.equipmentmanage.vo.*;
import cn.iocoder.an.module.business.dal.dataobject.equipmentmanage.EquipmentManageDO;
import cn.iocoder.an.module.business.service.equipmentmanage.EquipmentManageService;
import org.springframework.web.multipart.MultipartFile;

@Tag(name = "管理后台 - 设备台账")
@RestController
@RequestMapping("/business/equipment-manage")
@Validated
public class EquipmentManageController {

    @Resource
    private EquipmentManageService equipmentManageService;

    @Resource
    private EquipmentKeepConfigService equipmentKeepConfigService;


    @Resource
    private EquipmentCheckPlanMapper equipmentCheckPlanMapper;

    @Resource
    private WarningConfigMapper warningConfigMapper;


    @PostMapping("/create")
    @Operation(summary = "创建设备台账")
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:create')")
    public CommonResult<Long> createEquipmentManage(@Valid @RequestBody EquipmentManageSaveReqVO createReqVO) {
        return success(equipmentManageService.createEquipmentManage(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新设备台账")
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:update')")
    public CommonResult<Boolean> updateEquipmentManage(@Valid @RequestBody EquipmentManageSaveReqVO updateReqVO) {
        equipmentManageService.updateEquipmentManage(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除设备台账")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:delete')")
    public CommonResult<Boolean> deleteEquipmentManage(@RequestParam("id") Long id) {
        equipmentManageService.deleteEquipmentManage(id);
        return success(true);
    }

    @DeleteMapping("/delete-list")
    @Parameter(name = "ids", description = "编号", required = true)
    @Operation(summary = "批量删除设备台账")
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:delete')")
    public CommonResult<Boolean> deleteEquipmentManageList(@RequestParam("ids") List<Long> ids) {
        equipmentManageService.deleteEquipmentManageListByIds(ids);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得设备台账")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:query')")
    @TransMethodResult
    public CommonResult<EquipmentManageRespVO> getEquipmentManage(@RequestParam("id") Long id) {
        EquipmentManageDO equipmentManage = equipmentManageService.getEquipmentManage(id);
        return success(BeanUtils.toBean(equipmentManage, EquipmentManageRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得设备台账分页")
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:query')")
    @TransMethodResult
    public CommonResult<PageResult<EquipmentManageRespVO>> getEquipmentManagePage(@Valid EquipmentManagePageReqVO pageReqVO) {
        PageResult<EquipmentManageDO> pageResult = equipmentManageService.getEquipmentManagePage(pageReqVO);
        PageResult<EquipmentManageRespVO> bean = BeanUtils.toBean(pageResult, EquipmentManageRespVO.class);
        bean.getList().forEach(item -> {
            String allName = equipmentKeepConfigService.getAllName(2, item.getId());
            item.setKeepConfigName(allName);
        });
        return success(bean);
    }

    @GetMapping("/checkPage")
    @Operation(summary = "获得设备台账点检分页")
    @TransMethodResult
    public CommonResult<PageResult<EquipmentManageRespVO>> getEquipmentManageCheckPage(@Valid EquipmentManagePageReqVO pageReqVO) {
        PageResult<EquipmentManageDO> pageResult = equipmentManageService.getEquipmentManageCheckPage(pageReqVO);
        PageResult<EquipmentManageRespVO> bean = BeanUtils.toBean(pageResult, EquipmentManageRespVO.class);


        //1.先获取预警配置项 按照预警天数从小到大排序
        LambdaQueryWrapperX<WarningConfigDO> configWrapper = new LambdaQueryWrapperX<>();
        configWrapper.eq(WarningConfigDO::getWarningType, 2);
        configWrapper.orderByAsc(WarningConfigDO::getWarningDays);
        List<WarningConfigDO> configList = warningConfigMapper.selectList(configWrapper);

        for (EquipmentManageRespVO respVO : bean.getList()) {
            if (respVO.getLastCheckTime() == null) {
                continue;
            }

            //3. 查询待点检计划
            LambdaQueryWrapperX<EquipmentCheckPlanDO> planWrapper = new LambdaQueryWrapperX<>();
            // 添加条件：绑定了设备类型的
            planWrapper.isNotNull(EquipmentCheckPlanDO::getEquipmentTypeId);
            planWrapper.likeIfPresent(EquipmentCheckPlanDO::getEquipmentTypeName, respVO.getEquipmentClassifyName());
            planWrapper.orderByAsc(EquipmentCheckPlanDO::getCreateTime);
            List<EquipmentCheckPlanDO> planDOList = equipmentCheckPlanMapper.selectList(planWrapper);

            //使用点检频率和上次点检时间 计算下次点检时间  如果下次点检时间减去当前时间小于预警小时 提醒
            Long equipmentClassify = respVO.getEquipmentClassify();
            for (EquipmentCheckPlanDO planDO : planDOList) {
                List<Long> equipmentTypeId = planDO.getEquipmentTypeId();
                // 判断 equipmentClassify 是否在 equipmentTypeId 中
                if (equipmentTypeId != null && equipmentClassify != null && equipmentTypeId.contains(equipmentClassify)) {
                    System.out.println("equipmentClassify 在列表中");

                    //点检频率
                    Integer checkRepeat = planDO.getCheckRepeat().intValue();
                    //上次点检时间
                    LocalDateTime lastCheckTime = respVO.getLastCheckTime();
                    //下次点检按时间
                    LocalDateTime nextCheckTime = lastCheckTime.plusHours(checkRepeat);

                    respVO.setNextCheckTime(nextCheckTime);

                    LocalDateTime now = LocalDateTime.now();

                    // 计算从 now 到 nextCheckTime 之间的小时数（向下取整）
                    long remainingHours = Duration.between(now, nextCheckTime).toHours();

                   //保留小数（比如 2.5 小时），可以用下面的方法
                    double remainingHoursWithDecimal = Duration.between(now, nextCheckTime).toMillis() / (1000.0 * 60 * 60);


                    for (WarningConfigDO config : configList) {
                        //预警小时
                        Integer warningDays = config.getWarningDays();
                        if (remainingHoursWithDecimal <= warningDays) {
                            respVO.setColor(config.getWarningColor());
                            break;
                        }
                    }

                }

            }

        }

        return success(bean);
    }


    @GetMapping("/list")
    @Operation(summary = "获得所有设备")
    @TransMethodResult
    public CommonResult<List<EquipmentManageRespVO>> getEquipmentManageList(  @RequestParam String keyWords) {
        List<EquipmentManageDO> pageResult = equipmentManageService.getEquipmentManageList(keyWords);
        return success(BeanUtils.toBean(pageResult, EquipmentManageRespVO.class));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出设备台账 Excel")
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportEquipmentManageExcel(@Valid EquipmentManagePageReqVO pageReqVO,
                                           HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<EquipmentManageDO> list = equipmentManageService.getEquipmentManagePage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "设备台账.xlsx", "数据", EquipmentManageRespVO.class,
                BeanUtils.toBean(list, EquipmentManageRespVO.class));
    }

    @GetMapping("/get-import-template")
    @Operation(summary = "获得设备台账导入模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<EquipmentImportExcelVO> list = Arrays.asList(
                EquipmentImportExcelVO.builder().code("xxx").equipmentName("xx设备").deptName("市场部门").equipmentClassifyName("打孔设备")
                        .equipmentStatus(EquipmentStatusEnum.shutdown.getEquipmentStatus()).equipmentType(EquipmentTypeEnum.COMMON.getEquipmentType()).equipmentModel("YYY-2B").equipmentPower("20").equipmentWeight("20").equipmentTonnage("22").installPosition("六厂-2")
                        .installDate(new Date()).productionDate(new Date()).unit("xx单位").equipmentProducer("宁波xx设备生产有限公司").contacts("张伟").contactsNumber("18888888888").useType(EquipmentUsedEnum.USED.getUsedType())
                        .maintainDatetime(LocalDateTime.now()).nextMaintainDatetime(LocalDateTime.now()).lastMaintainTimeDamage(LocalDateTime.now()).nextMaintainTimeDamage(LocalDateTime.now()).lastCheckTime(LocalDateTime.now()).remark("该设备xxxxxx").build()
        );
        // 输出
        ExcelUtils.write(response, "设备台账导入模板.xlsx", "设备台账列表", EquipmentImportExcelVO.class, list);
    }


    @PostMapping("/import")
    @Operation(summary = "导入设备台账")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新，默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('business:equipment-manage:import')")
    public CommonResult<ImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                  @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
        List<EquipmentImportExcelVO> list = ExcelUtils.read(file, EquipmentImportExcelVO.class);
        return success(equipmentManageService.importEquipmentList(list, updateSupport));
    }



}